Skip to content

Add barrier option replication adjoint example - #25

Open
tylrcc wants to merge 1 commit into
auto-differentiation:mainfrom
tylrcc:example/replication-adjoint
Open

tylrcc wants to merge 1 commit into
auto-differentiation:mainfrom
tylrcc:example/replication-adjoint

Conversation

@tylrcc

@tylrcc tylrcc commented Nov 12, 2026

Copy link
Copy Markdown

Closes #20.

Python port of the AdjointReplication C++ example (Joshi's static replication of a down-and-out barrier option with European options), following the pattern of swap-adjoint.py:

  • Same setup as the C++ original: evaluation date 29 May 2006, down-and-out put, strike 101, barrier 70, spot 100, vol 0.20, flat 4% zero curve on the same node dates, kill loop over 26 fortnightly dates.
  • The portfolio construction (including the kill notionals, which are computed from recorded portfolio values, and the evaluation-date changes at each kill date) runs inside the recording, so one adjoint pass yields rhos, strike sensitivity, vega, delta, and barrier sensitivity.
  • The example cross-checks every adjoint against bump-and-reprice finite differences (eps = 1e-5) at the end.

Testing: the current QuantLibAAD wheel is not reachable from my sandbox, so I ran the identical example code against QuantLib-Risks 1.33.3 (the direct predecessor of QuantLibAAD; only the tape-construction lines and one payoff-width argument differ between the two APIs). It runs end to end: barrier option value 4.652838435318750, replicating portfolio 4.154324163665421, and all adjoints match bumping to within 2.1e-4 relative (worst case: vega, adjoint -7.045801 vs bump -7.047242; most are at 1e-5 or better).

One deliberate difference from the C++ code, also noted in the example: the C++ registers a single variable for the flat 4% rate shared by all nine curve nodes, so its rho is the sum over nodes. This port registers one input per node (all set to 4%) and reports the rhos per node; the per-node values sum to the C++-style sensitivity. Shout if you would prefer the single-variable form instead.

Note: this repo requires a signed CLA before merge (per CONTRIBUTING) — I understand it will be handled through the CLA flow.

Port of the AdjointReplication C++ example (the static replication of a
down-and-out barrier option with European options from Joshi, The
Concepts and Practice of Mathematical Finance, ch. 17). The replicating
portfolio is built on the tape - the notionals that kill the portfolio
value on the barrier are computed from recorded portfolio values - so a
single adjoint pass gives the sensitivities of the portfolio value to
the zero rates, the strike, the volatility, the underlying, and the
barrier level.

The example prints the reference barrier option value (4.652838435318750)
next to the replicating portfolio value (4.154324163665421) and
cross-checks every adjoint against bump-and-reprice finite differences.

One deliberate difference from the C++ code: it registers a single
variable for the flat 4% rate shared by all curve nodes, while this port
registers one input per node (all 4%) and reports the rhos per node.
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Barrier option replication example (AAD)

2 participants